package com.haiyi.test.qrcode;

import com.fpc.util.fileUtil.FileUtils;
//import cn.csg.upt.exception.BusinessException;
import com.google.zxing.BarcodeFormat;
import com.google.zxing.EncodeHintType;
import com.google.zxing.MultiFormatWriter;
import com.google.zxing.WriterException;
import com.google.zxing.common.BitMatrix;
import com.google.zxing.qrcode.QRCodeWriter;
import com.google.zxing.qrcode.decoder.ErrorCorrectionLevel;

import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.geom.AffineTransform;
import java.awt.image.AffineTransformOp;
import java.awt.image.BufferedImage;
import java.io.*;
import java.net.URLDecoder;
import java.util.Base64;
import java.util.HashMap;
import java.util.Map;

/**
 * 二维码工具类
 * Created by LFQ on 2020-12-10.
 */
public class QRCodeUtil {

    private static final int BLACK = 0xFF000000;

    private static final int WHITE = 0x00FFFFFF;

    public static BufferedImage toBufferedImage(BitMatrix matrix) {
        int width = matrix.getWidth();
        int height = matrix.getHeight();
        BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB);

        int[] pixels = new int[width * height];
        int index = 0;

        for(int y = 0; y < height; ++y) {
            for(int x = 0; x < width; ++x) {
                pixels[index++] = matrix.get(x, y) ? BLACK : WHITE;
            }
        }

        image.setRGB(0, 0, width, height, pixels, 0, width);
        return image;
    }

    public static void writeToStream(BitMatrix matrix, String format, OutputStream stream)
            throws IOException {
        BufferedImage image = toBufferedImage(matrix);
        if (!ImageIO.write(image, format, stream)) {
            throw new IOException("Could not write an image of format " + format);
        }
    }

    /**
     *
     * @param content 文件内容
     * @param width 宽度
     * @param height 高度
     * @param format 二维码图片格式
     * @return
     * @throws WriterException
     * @throws IOException
     */
    public static byte[] generateQRCodeImage(String content, int width, int height, String format) throws Exception {
        ByteArrayOutputStream byteArrayOutputStream = null;
        try{
            QRCodeWriter qrCodeWriter = new QRCodeWriter();
            BitMatrix bitMatrix = qrCodeWriter.encode(content, BarcodeFormat.QR_CODE, width, height);
            byteArrayOutputStream = new ByteArrayOutputStream();
            QRCodeUtil.writeToStream(bitMatrix, format, byteArrayOutputStream);
        }catch (Exception e){
            throw new RuntimeException("生成二维码失败！");
        }finally {
            try {
                byteArrayOutputStream.close();
            }catch (Exception e){}
        }
        return  byteArrayOutputStream.toByteArray();
    }

    /**
     *
     * @param content 文件内容
     * @param width 宽度
     * @param height 高度
     * @param format 二维码图片格式
     * @return
     * @throws WriterException
     * @throws IOException
     */
    public static byte[] generateQRCodeImage(String content, int width, int height, String format,String param) throws Exception {
        ByteArrayOutputStream byteArrayOutputStream = null;
        try{
            QRCodeWriter qrCodeWriter = new QRCodeWriter();
            BitMatrix bitMatrix = qrCodeWriter.encode(content, BarcodeFormat.QR_CODE, width, height);
            byteArrayOutputStream = new ByteArrayOutputStream();
            QRCodeUtil.writeToStream(bitMatrix, format, byteArrayOutputStream,width,height);
        }catch (Exception e){
            throw new RuntimeException("生成二维码失败！");
        }finally {
            try {
                byteArrayOutputStream.close();
            }catch (Exception e){}
        }
        return  byteArrayOutputStream.toByteArray();
    }

    public static void writeToStream(BitMatrix matrix, String format, OutputStream stream,int width,int height)
            throws IOException {
        BufferedImage image = toBufferedImage(matrix);
        Graphics2D grap=image.createGraphics();
        grap.setBackground(Color.white);//设置背景色
        grap.setColor(Color.red);//设置二维码颜色
        grap.clearRect(0, 0, width, height);//清除下画板内容
        if (!ImageIO.write(image, format, stream)) {
            throw new IOException("Could not write an image of format " + format);
        }
    }
   //白色边框达到最小：  150 180  210 240 270   可以看出是30的倍数
    private static final int LOGO_WIDTH = 50;
    private static final int LOGO_HEIGHT = 50;
    private static final int IMAGE_WIDTH = 210;
    private static final int IMAGE_HEIGHT = 210;
    private static final int IMAGE_HALF_WIDTH = LOGO_WIDTH / 2;
    private static final int FRAME_WIDTH = 2; // 距离二维码
    private static final MultiFormatWriter mutiWriter = new MultiFormatWriter();
    /**
      * @Description   消费报告5星 二维码
      * @Date 2023/1/9
      **/
    public static BufferedImage genBarcode(String content,String srcImagePath,Integer starLevel)
            throws WriterException, IOException {
        BufferedImage scaleImage = scale(srcImagePath);
        int[][] srcPixels = new int[LOGO_WIDTH][LOGO_HEIGHT];
        for (int i = 0; i < scaleImage.getWidth(); i++) {
            for (int j = 0; j < scaleImage.getHeight(); j++) {
                srcPixels[i][j] = scaleImage.getRGB(i, j);
            }
        }
        Map<EncodeHintType, Object> hint = new HashMap<>();
        hint.put(EncodeHintType.CHARACTER_SET, "utf-8");
        hint.put(EncodeHintType.ERROR_CORRECTION, ErrorCorrectionLevel.H);
        hint.put(EncodeHintType.MARGIN, 0);//边框
        // 生成二维码
        BitMatrix matrix = mutiWriter.encode(content, BarcodeFormat.QR_CODE, IMAGE_WIDTH, IMAGE_HEIGHT, hint);
        // 二维矩阵转为一维像素数组
        int halfW = matrix.getWidth() / 2;
        int halfH = matrix.getHeight() / 2;
        int[] pixels = new int[IMAGE_WIDTH * IMAGE_HEIGHT];
        for (int y = 0; y < matrix.getHeight(); y++) {
            for (int x = 0; x < matrix.getWidth(); x++) {
                // 左上角颜色,根据自己需要调整颜色范围和颜色
              /*  if (x > 0 && x < 55 && y > 0 && y < 55) {
                    Color color = new Color(231, 144, 56);
                    int colorInt = color.getRGB();
                    pixels[y * IMAGE_WIDTH + x] = matrix.get(x, y) ? colorInt : 16777215;
                }
                // 读取图片
                else*/ if (x > halfW - IMAGE_HALF_WIDTH && x < halfW + IMAGE_HALF_WIDTH && y > halfH - IMAGE_HALF_WIDTH
                        && y < halfH + IMAGE_HALF_WIDTH) {
                    pixels[y * IMAGE_WIDTH + x] = srcPixels[x - halfW + IMAGE_HALF_WIDTH][y - halfH + IMAGE_HALF_WIDTH];
                } else if ((x > halfW - IMAGE_HALF_WIDTH - FRAME_WIDTH && x < halfW - IMAGE_HALF_WIDTH + FRAME_WIDTH
                        && y > halfH - IMAGE_HALF_WIDTH - FRAME_WIDTH && y < halfH + IMAGE_HALF_WIDTH + FRAME_WIDTH)
                        || (x > halfW + IMAGE_HALF_WIDTH - FRAME_WIDTH && x < halfW + IMAGE_HALF_WIDTH + FRAME_WIDTH
                        && y > halfW - IMAGE_HALF_WIDTH - FRAME_WIDTH
                        && y < halfH + IMAGE_HALF_WIDTH + FRAME_WIDTH)
                        || (x > halfW - IMAGE_HALF_WIDTH - FRAME_WIDTH && x < halfW + IMAGE_HALF_WIDTH + FRAME_WIDTH
                        && y > halfH - IMAGE_HALF_WIDTH - FRAME_WIDTH
                        && y < halfH - IMAGE_HALF_WIDTH + FRAME_WIDTH)
                        || (x > halfW - IMAGE_HALF_WIDTH - FRAME_WIDTH && x < halfW + IMAGE_HALF_WIDTH + FRAME_WIDTH
                        && y > halfH + IMAGE_HALF_WIDTH - FRAME_WIDTH
                        && y < halfH + IMAGE_HALF_WIDTH + FRAME_WIDTH)) {
                    pixels[y * IMAGE_WIDTH + x] = 0xfffffff;
                    // 在图片四周形成边框
                } else {
                    // 二维码颜色
                   /* int num1 = (int) (50 - (50.0 - 13.0) / matrix.getHeight() * (y + 1));
                    int num2 = (int) (200 - (165.0 - 72.0) / matrix.getHeight() * (y + 1));
                    int num3 = (int) (162 - (162.0 - 107.0) / matrix.getHeight() * (y + 1));
                    Color color = new Color(num1, num2, num3);*/
                    Color color =getColor( starLevel);
                    int colorInt = color.getRGB();
                    // 此处可以修改二维码的颜色，可以分别制定二维码和背景的颜色；
                    pixels[y * IMAGE_WIDTH + x] = matrix.get(x, y) ? colorInt : 16777215;
                    // 0x000000:0xffffff
                }
            }
        }
        BufferedImage image = new BufferedImage(IMAGE_WIDTH, IMAGE_HEIGHT, BufferedImage.TYPE_INT_RGB);
        image.getRaster().setDataElements(0, 0, IMAGE_WIDTH, IMAGE_HEIGHT, pixels);

        return image;
    }

    private static BufferedImage scale(String srcImageFile) throws IOException {
        // 缩放比例
        double ratio;
        File file = new File(srcImageFile);
        BufferedImage srcImage = ImageIO.read(file);
        Image destImage = srcImage.getScaledInstance(QRCodeUtil.LOGO_WIDTH, QRCodeUtil.LOGO_HEIGHT,
                BufferedImage.SCALE_SMOOTH);
        // 计算比例
        if ((srcImage.getHeight() > QRCodeUtil.LOGO_WIDTH) || (srcImage.getWidth() > QRCodeUtil.LOGO_HEIGHT)) {
            if (srcImage.getHeight() > srcImage.getWidth()) {
                ratio = (new Integer(QRCodeUtil.LOGO_WIDTH)).doubleValue() / srcImage.getHeight();
            } else {
                ratio = (new Integer(QRCodeUtil.LOGO_HEIGHT)).doubleValue() / srcImage.getWidth();
            }
            AffineTransformOp op = new AffineTransformOp(AffineTransform.getScaleInstance(ratio, ratio), null);
            destImage = op.filter(srcImage, null);
        }
        // 补白
        BufferedImage image = new BufferedImage(QRCodeUtil.LOGO_WIDTH, QRCodeUtil.LOGO_HEIGHT,
                BufferedImage.TYPE_INT_RGB);
        Graphics2D graphic = image.createGraphics();
        graphic.setColor(Color.white);
        graphic.fillRect(0, 0, QRCodeUtil.LOGO_WIDTH, QRCodeUtil.LOGO_HEIGHT);
        if (QRCodeUtil.LOGO_HEIGHT == destImage.getWidth(null))
            graphic.drawImage(destImage, 0, (QRCodeUtil.LOGO_WIDTH - destImage.getHeight(null)) / 2,
                    destImage.getWidth(null), destImage.getHeight(null), Color.white, null);
        else
            graphic.drawImage(destImage, (QRCodeUtil.LOGO_HEIGHT - destImage.getWidth(null)) / 2, 0,
                    destImage.getWidth(null), destImage.getHeight(null), Color.white, null);
        graphic.dispose();
        destImage = image;
        return (BufferedImage) destImage;
    }

    private static Color getColor(Integer starLevel){
        Color color;
        switch(starLevel)
        {
            case 1:
                 color = new Color(138, 208, 109);
                break;
            case 2:
                color = new Color(0, 207, 168);
                break;
            case 3:
                color = new Color(0, 213, 223);
                break;
            case 4:
                color = new Color(2, 168, 223);
                break;
            case 5:
                color = new Color(0, 128, 210);
                break;
            default:
                 color = new Color(0, 0, 0);
        }
        return color;
    }


    /**
     * 添加在指定位置追加图片水印
     *
     * @param waterImage
     *            --水印文件地址
     * @param img
     *            -- 目标
     * @param x
     *            --x坐标
     * @param y
     *            --y坐标
     */
    public final static BufferedImage addWaterImage(String waterImage, BufferedImage img, int x, int y) {
        try {
            // 目标文件
            int width = img.getWidth(null);
            int height = img.getHeight(null);
            File _filebiao = new File(waterImage);
            BufferedImage image = ImageIO.read(_filebiao);
            Graphics g = image.createGraphics();
            g.drawImage(img, x, y, width, height, null);
            g.dispose();
            return image;
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }
    
    public final static BufferedImage scaleImage(BufferedImage images){
        // 4、获取图片的缩放【宽高都是*了缩放比例的再取整】
        Image scaledInstance = images.getScaledInstance(Double.valueOf(images.getWidth()*0.45).intValue(),Double.valueOf(images.getHeight() * 0.45).intValue(),Image.SCALE_DEFAULT);
        // 5、将Image类型转换成BufferedImage对象[BufferedImage.TYPE_INT_ARGB：表示具有8位RGBA颜色成分的整数像素的图像]
        BufferedImage newImage = new BufferedImage(Double.valueOf(images.getWidth()*0.45).intValue(),Double.valueOf(images.getHeight() * 0.45).intValue(),BufferedImage.TYPE_INT_ARGB);
        // 一个新的图形上下文，这是这个图形上下文的副本
        Graphics g = newImage.getGraphics();
        // 绘制图片大小
        boolean b = g.drawImage(scaledInstance, 0, 0, null);
        // 释放文件资源
        g.dispose();

        return newImage;
    }


    public static void main(String[] args) {
        String content = "http://www.baidu.com";
        BufferedImage images= null;
        Integer starLevel=1;
        try {
            StringBuffer logPathbf= new StringBuffer();
            logPathbf.append("QRCode/logo-").append(starLevel).append(".png");
            String logPath = URLDecoder.decode(FileUtils.getAbsolutePath(logPathbf.toString()), "UTF-8");
            images = QRCodeUtil.genBarcode(content,logPath,starLevel);
            // 追加二维码模板
            StringBuffer backgroundPathbf= new StringBuffer();
            backgroundPathbf.append("QRCode/background-").append(starLevel).append(".jpg");
            String backgroundPath = URLDecoder.decode(FileUtils.getAbsolutePath(backgroundPathbf.toString()), "UTF-8");
            images = QRCodeUtil.addWaterImage(backgroundPath, images, 32, 30);
            //将图片转换陈字符串
          /*  ByteArrayOutputStream stream = new ByteArrayOutputStream();
            ImageIO.write(images, "png", stream);
            String base64Image= Base64.getEncoder().encodeToString(stream.toByteArray());
            stream.flush();
            stream.close();*/
            File imgfile = new File("C:\\Users\\fupc\\Desktop\\ld相关\\qrcode.png");
            ImageIO.write(images, "png", imgfile);
            //return base64Image;
        } catch (WriterException e) {
            e.printStackTrace();
           // throw new BusinessException("二维码生成失败");
        } catch (IOException e) {
            e.printStackTrace();
           // throw new BusinessException("二维码生成失败，IO异常");
        }

       /* Integer width = 80;
        Integer height = 80;
        String fileType = "png";
        String fullFilePath = "D:\\workspace\\rept\\qrcode\\myQRCode124."+fileType;
        try {
            byte[] bytes = generateQRCodeImage(content, width, height, fileType);
            PDFUtil.byteToFile(bytes,fullFilePath);
        }catch (Exception e){

        }*/
    }




}
